package com.zhuiyun.project.api.system.notification.ws;

import com.zhuiyun.project.common.controller.BaseController;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.CrossOrigin;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @ClassName NotificationWs
 * @Description TODO 系统通知
 * @Author lzy
 * @Date 2023/7/12 15:48
 **/
@Component
@Slf4j
//@ServerEndpoint("/system/notification/{userId}")
@ServerEndpoint("/system/notification")
@CrossOrigin
public class NotificationWs extends BaseController {

    private Session session;

    //concurrent包的线程安全Set，用来存放每个客户端对应的WebSocket对象。
    private static CopyOnWriteArraySet<NotificationWs> webSocketUtils = new CopyOnWriteArraySet<>();

    // 用来存在线连接数
    private static Map<String, Session> sessionPool = new HashMap<>();

    /**
     * 链接成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) {
        String userId = String.valueOf(getUserId());
        try {
            this.session = session;
            webSocketUtils.add(this);
            sessionPool.put(userId, session);
            sendOneMessage(userId, "连接成功");
            log.info("【websocket消息】有新的连接，总数为:" + webSocketUtils.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 链接关闭调用的方法
     */
    @OnClose
    public void onClose() {
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message
     * @param
     */
    @OnMessage
    public void onMessage(@PathParam(value = "userId") String userId, String message) {

    }

    /**
     * 发送错误时的处理
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {

    }


    /**
     * 推消息给前端
     *
     * @param userId
     * @param message
     * @return
     */
    public static Runnable sendOneMessage(String userId, String message) {
        Session session = sessionPool.get(userId);
        if (session != null && session.isOpen()) {
            try {
                log.info("【推给前端消息】 :" + message);

                //高并发下，防止session占用期间，被其他线程调用
                synchronized (session) {
                    session.getBasicRemote().sendText(message);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

}
